{% extends "baseD.html" %}

{% block headtitle %}- Calibrate PTZ Camera{% endblock %}

{% block divtitle %}- Calibrate PTZ Camera{% endblock %}

{% block css %}
	<link href="/live3dstatic/css/build.css" rel="stylesheet" type="text/css" media="screen" />
{% endblock %}

{% block scripts %}
	<script type="text/javascript" src="/live3dstatic/scripts/helperFunctions.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/matrix.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/simplex.js"></script>
	<script type="text/javascript" src="/live3dstatic/scripts/new_pantiltcalibration.js"></script>
	
	<script type="text/javascript">
		
		var correspondences = [
		{% for corr in corrs %}
			{id: {{corr.index}}, lat: {{corr.latitude}}, lon: {{corr.longitude}}, alt: {{corr.altitude}},
							     u: {{corr.u}}, v: {{corr.v}},
							     pan: {{corr.pan}}, tilt: {{corr.tilt}}, zoom:{{corr.zoom}} },
		{% endfor %}
		]
		// id is {{ptzScene.index}}
		{% ifequal ptzScene.index 1 %}
		// tucson scene.
		var groundTruth = {lat: 32.224309520459805, lon: -110.97219168248927, alt: 756.6098436120883};
		{% endifequal %}
		
		{% ifequal ptzScene.index 2 %}
		// wichita
		var groundTruth = {lat: 37.68677004571261, lon: -97.34038636835106, alt: 461.3278203004477};
		{% endifequal %}
		
		{% ifequal ptzScene.index 3 %}
		// pittsburgh.
		var groundTruth = {lat: 40.444240226111745, lon: -79.95314897973732, alt: 399.6533044214227};
		{% endifequal %}
		{% ifequal ptzScene.index 4 %}
		// montana.
		var groundTruth = {lat: 46.86120285084618, lon: -113.98896649837229, alt: 1008.7736788189497};
		{% endifequal %}
		{% ifequal ptzScene.index 5 %}
		// rochester.
		var groundTruth = {lat: 43.126971, lon: -77.632214, alt: 179};
		{% endifequal %}
		{% ifequal ptzScene.index 6 %}
		// montana 2
		var groundTruth = {lat: 45.66813821124887, lon: -111.04992863696047, alt: 1521.8304225943373}
		{% endifequal %}
		
		
		function initPTZ(){
			document.getElementById('numcorrs').innerHTML = '' + correspondences.length + ' correspondences.';
			var magnitudes = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50];
			var numCorrupted = [0,1,2,3,4,5,6,7,8,9,10];
			var percents = [];
			for (var i in numCorrupted){
				percents.push(numCorrupted[i] / 30);
			}
			var trials = 15;
			
			for (var m in magnitudes){
				for (var p in percents){
					for (var t = 0; t < trials; t++){
						calibrateWithError(magnitudes[m], percents[p]);
					}
				}
			}
			
		}
		
		function corruptPoint(point, magnitude){
			// find the latitude +- magnitue meters away from the point's location.
			var latPerMeter = 0.000001 / distance(point.lat,point.lon,point.alt,point.lat+0.000001,point.lon,point.alt);
			var lonPerMeter = 0.000001 / distance(point.lat,point.lon,point.alt,point.lat,point.lon+0.000001,point.alt);
			var maxLat = point.lat + latPerMeter * magnitude
			var minLat = point.lat - latPerMeter * magnitude
			var maxLon = point.lon + lonPerMeter * magnitude
			var minLon = point.lon - lonPerMeter * magnitude
			var maxAlt = point.alt + magnitude
			var minAlt = point.alt - magnitude
			
			// choose some new point uniformly in this square.
			var alphaLat = Math.random();
			var alphaLon = Math.random();
			var alphaAlt = Math.random();
			var newLat = maxLat * alphaLat + minLat * (1 - alphaLat);
			var newLon = maxLon * alphaLon + minLon * (1 - alphaLon);
			var newAlt = maxAlt * alphaAlt + minAlt * (1 - alphaAlt);
			
			// return corrupted point.
			return {id: point.id, lat: newLat, lon: newLon, alt: newAlt,
							     u: point.u, v: point.v,
							     pan: point.pan, tilt: point.tilt, zoom:point.zoom };
			
		}
		
		function calibrateWithError(magnitude, percent){
			var origin = {lat: {{originLatitude}}, lon: {{originLongitude}}, alt: {{originAltitude}} };
			var panRange = new Array({{ptzScene.panLeftRange}}, {{ptzScene.panRightRange}});
			var tiltRange = new Array({{ptzScene.tiltDownRange}}, {{ptzScene.tiltUpRange}});
			var zoomRange = new Array({{ptzScene.zoomOutRange}}, {{ptzScene.zoomInRange}});
			
			var ptzScene = new PTZScene({{ptzScene.index}}, origin, panRange, tiltRange, zoomRange, 
			                        {{ptzScene.width}}, {{ptzScene.height}}, 340, 120);
			
			var corruptIndices = range(0,correspondences.length);
			corruptIndices = randomSample(corruptIndices, percent);
			
					
			for (var i = 0; i < correspondences.length; i++){
				var corr = correspondences[i];
				if (corruptIndices.indexOf(i) >= 0){// if the correspondence is corrupt,
				
					// corrupt the point.
					var corrupt = corruptPoint(corr, magnitude);
					alert('corrupting ' + i + ',' + distance(corrupt.lat, corrupt.lon, corrupt.alt, corr.lat, corr.lon, corr.alt))
					
					ptzScene.add_correspondence(corrupt.id, corrupt.lat,corrupt.lon,corrupt.alt,
											  corrupt.u, corrupt.v,
											  corrupt.pan, corrupt.tilt, corrupt.zoom);
				} else {
					// don't corrupt.
					ptzScene.add_correspondence(corr.id, corr.lat,corr.lon,corr.alt,
											  corr.u, corr.v,
											  corr.pan, corr.tilt, corr.zoom);
				}
			}
			
			//ptzScene.calibrate(20000, 10); // projection error
			result = ptzScene.calibrate(20000, 0.0000001, {% if admin %}true{%else%}false{% endif %}, false); // angular error
			var solution = result.solution;
			
			var latsPerMeter = 0.00001 / distance(origin.lat, origin.lon, 0, origin.lat+0.00001, origin.lon, 0);
			var lonsPerMeter = 0.00001 / distance(origin.lat, origin.lon, 0, origin.lat, origin.lon+0.00001, 0);
			var cameraLon = solution[0] * lonsPerMeter + origin.lon;
			var cameraLat = solution[1] * latsPerMeter + origin.lat;
			var cameraAlt = solution[2] + origin.alt;
			
			var cameraError = distance(cameraLat, cameraLon, cameraAlt, groundTruth.lat, groundTruth.lon, groundTruth.alt)
			var error = getTotalAngularError(ptzScene, solution, corruptIndices);
			
			var corruptionHTML = document.getElementById('corruptionResults').innerHTML;
			corruptionHTML = corruptionHTML + magnitude + ',' + (percent * 30) + ',' + error + ',' + cameraError + '<br/>'
			document.getElementById('corruptionResults').innerHTML = corruptionHTML;
		}
		
		
		function getTotalAngularError(ptzScene, solution, corruptIndices){
			// the optimization gives results in terms of [0,2] error.
			// this converts those errors into degrees and reports them
			// to the browser.  ignore any results from corruptIndices.
			
			var allM = ptzScene.make_many_projection_matrices(solution);

			var n = ptzScene.x.length;
			var sumErrorDeg = 0;
			var uncorrupted = 0;

			for (var i = 0; i < n; i++){
				if (corruptIndices.indexOf(i) >= 0){// if the correspondence is corrupt,
					continue;
				}
				var M = allM[i];
				var zeroToTwoError = ptzScene.angular_error(M, solution, ptzScene.u[i], ptzScene.v[i], ptzScene.x[i],ptzScene.y[i], ptzScene.z[i])
				var errRad = Math.acos(1- zeroToTwoError);
				var errDeg = 180.0 / Math.PI * errRad;
				sumErrorDeg = sumErrorDeg + errDeg;
				uncorrupted++;
			}

			return sumErrorDeg / uncorrupted;
		}
		
		
		
	</script>
{% endblock %}

{% block onload %}initPTZ(){% endblock %}

{% block content %}
	
    <div id="contentpage"  style="margin-left:40px; margin-right:40px;">
<p> Your scene is being calibrated.  You will soon be redirected to view your scene.  
If your browser doesn't redirect you after a few seconds, <a href='viewScene?scene={{ptzScene.index}}'>click here.</a> </p>
{% if admin %}
<div id="result" style="display:none;"></div>
<div id="numcorrs"></div>

<div id="corruptionResults"><b>Magnitude</b>, <b>Percent</b>, <b>Error</b>, <b>Camera Position Error</b><br/></div>


<br/>
<br/>
<div id="simplex"></div>

{% endif %}

    </div><!-- end contentpage --> 
{% endblock %}
		
{% block scripts2 %} {% endblock %}